﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tomahawk.Runtime.Timeline;
using Tomahawk.Runtime.Resources;
using System.Xml.Serialization;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace Tomahawk.Runtime.Canvas.Sprite
{
    internal sealed class SpriteEffect : LoadableResource
    {
        private string effectFile;

        private Effect effect;
        internal Effect Effect { get { return effect; } }

        internal SpriteEffect(string effectFile)
        {
            this.effectFile = effectFile;
        }

        private bool IsValidEffect(Effect effect)
        {
            bool valid = true;
            valid = valid && (effect.Techniques.Count == 1);
            valid = valid && (effect.Techniques[0].Passes.Count == 1);
            return valid;
        }

        /// <summary>
        /// Provide this method in the derived type to perform the custom loading of the assets
        /// </summary>
        protected override bool OnLoad(GraphicsDevice graphics, ContentManager contentManager)
        {
            Effect effect = contentManager.Load<Effect>(effectFile);

            if (IsValidEffect(effect))
            {
                lock (Engine.ResourceLock)
                {
                    this.effect = effect.Clone(graphics);
                }

                foreach (EffectParameter parameter in this.effect.Parameters)
                {
                    if (parameter.ParameterType == EffectParameterType.Texture)
                    {
                        EffectAnnotation annotation = parameter.Annotations["ResourceName"];
                        if (annotation != null)
                        {
                            string textureFile = annotation.GetValueString();
                            Texture texture = contentManager.Load<Texture>(textureFile);
                            parameter.SetValue(texture);
                        }
                    }
                }
            }

            return true;
        }

        #region Rendering

        public delegate void LoadEffectParametersDelegate(Effect effect);
        public event LoadEffectParametersDelegate OnLoadEffectParameters;

        internal void Begin()
        {
            if (this.effect != null && !this.effect.IsDisposed)
            {
                OnLoadEffectParameters(this.effect);
                this.effect.Begin();
                this.effect.CurrentTechnique.Passes[0].Begin();
            }
        }

        internal void End()
        {
            if (this.effect != null && !this.effect.IsDisposed)
            {
                this.effect.CurrentTechnique.Passes[0].End();
                this.effect.End();
            }
        }
        #endregion
    }
}
